package interpreter

import (
	"parse/src/utils"
	"reflect"
)

type BaseFunction struct {
	*BaseData
	Name string
}

// 实例化
func NewBaseFunction(name string) *BaseFunction {
	temp := &BaseFunction{NewBaseData(), name}
	temp.InitBaseFunction(name)
	return temp
}

// 初始化
func (b *BaseFunction) InitBaseFunction(name string) {
	b.InitBaseData()
	if name != "" { // 普通函数
		b.Name = name
	} else { // 匿名函数
		b.Name = "<anonymous>"
	}
}

// 创建新的内容
func (b *BaseFunction) GenerateNewContext(name string) *Context {
	newContext := NewContext(b.Name, b.Context, b.PosStart)
	if newContext.Parent != nil {
		newContext.SymbolTable = GlobalSymbolTable
	} else {
		newContext.SymbolTable = GlobalSymbolTable
	}
	return newContext
}

// 检查参数 个数
func (b *BaseFunction) CheckArgs(argNames []string, args []interface{}) *RTResult {
	res := NewRTResult()

	// 比较参数名字与参数个数，如果参数多于参数名字就报错
	if len(args) > len(argNames) {
		return res.Failure(NewError(b.PosStart, b.PosEnd, "传递参数个数错误", reflect.TypeOf(b).String()+"参数太多了，期望是"+string(len(args))+"；却给了"+string(len(argNames))+"个参数"))
	}
	if len(args) < len(argNames) {
		return res.Failure(NewError(b.PosStart, b.PosEnd, "传递参数个数错误", reflect.TypeOf(b).String()+"参数太多了，期望是"+string(len(args))+"；却给了"+string(len(argNames))+"个参数"))
	}
	return res.Success(nil)
}

// 得到每个参数
func (b *BaseFunction) PopulateArgs(argNames []string, args []interface{}, execCtx interface{}) {
	for i := 0; i < len(args); i++ {
		argName := argNames[i]
		argValue := args[i]
		utils.RunFunc(argValue, "SetContext", execCtx)
		execCtx.(*Context).SymbolTable.Set(argName, argValue)
	}
}

// 检验参数个数是否正确，并且将参数填充进全局变量表
func (b *BaseFunction) CheckAndPopulateArgs(argNames []string, args []interface{}, execCtx interface{}) *RTResult {
	res := NewRTResult()
	res.Register(b.CheckArgs(argNames, args))
	if res.ShouldReturn() != nil {
		return res
	}
	b.PopulateArgs(argNames, args, execCtx)
	return res.Success(nil)
}
